#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include "../utility/assert_helper.h"
#include "../utility/file_helper.h"
#include "../utility/charset_convert.h"
//#include "../hive_access/nt_hive.h"

#include "windows_information.h"
#include "reg_accessor.h"

//extern Windows_Manager	g_windows_informations;
const char *HIVE_SYSTEM = "/system32/config";
bool Hive_Accessor::s_is_current_controlset_maped = false;

const char *HKEY_ROOTS[HKEY_INVALID_ROOT] = {
	"HKEY_LOCAL_MACHINE",
	"HKEY_USERS",
	"HKEY_CLASS_ROOT",
	"HKEY_CURRENT_USER",
	"HKEY_CURRENT_CONFIG"};

/*
 *
 * name: 建立表连接关系
 * @param
 * path - 键路径
 * file - 表文件名(如果为映射表则为被映射的主键名)
 * @return
 */
Link_Relation::Link_Relation(const std::string & key, const std::string & tname)
{
	is_shadow_ = false;
	key_name(key);
	target(tname);
}

Link_Relation::~Link_Relation()
{
}

void
Link_Relation::key_name(const std::string & name)
{
	key_name_ = name;
}

const std::string &
Link_Relation::key_name() const
{
	return key_name_;
}

void
Link_Relation::target(const std::string & name)
{
	target_ = name;
	//if (std::string(HKEY_ROOTS[HKEY_LOCAL_MACHINE]) == target_ ||
		//std::string(HKEY_ROOTS[HKEY_USERS]) == target_) {
		//is_shadow_ = true;
	//}
}

const std::string &
Link_Relation::target() const
{
	return target_;
}

bool
Link_Relation::shadow() const
{
	return is_shadow_;
}

void
Link_Relation::shadow(bool flag)
{
	is_shadow_ = flag;
}

void
Hive_Root::root_key(const std::string & key)
{
	root_key_ = key;
	for (int i = 0; i < HKEY_INVALID_ROOT; ++i) {
		if (HKEY_ROOTS[i] == root_key_) root_type_ = static_cast<HKEY>(i);
	}
}

const std::string &
Hive_Root::root_key() const
{
	return root_key_;
}

HKEY
Hive_Root::root_type() const
{
	return root_type_;
}

bool
Hive_Root::add_relation(const Link_Relation & link)
{
	Link_Relations::iterator end = sub_keys_.end();
	for (Link_Relations::iterator i = sub_keys_.begin(); i != end; ++i) {
		if (i->key_name() == link.key_name()) {
			return false;	// 不允许有相同的key
		}
	}
	sub_keys_.push_back(link);
	return true;
}

const Hive_Root::Link_Relations &
Hive_Root::link_relations() const
{
	return sub_keys_;
}

std::string & 
Hive_Root::link_relation(const std::string & key_name)
{
	static std::string s_str_nil;
	Link_Relations::iterator end = sub_keys_.end();
	for (Link_Relations::iterator index = sub_keys_.begin(); index != end; ++index) {
		if (index->key_name_ == key_name) {
			return index->target_;
		}
	}
	return s_str_nil;
}

Hive_Accessor::Hive_Accessor(const Windows_Information * win_info)
{
	IF_NULL_RETURN(win_info);
	hive_ = NULL;
	origin_offset_ = cdofs_ = 0;
/*	if (win_info->get_windows_version() > WINDOWS_ME &&
	win_info->get_windows_version() < WINDOWS_VISTA) {
		fill_linked_relation_array(win_info);
	}*/
	fill_linked_relation_array(win_info); //todo temp
	printf("ver = %d\n", win_info->get_windows_version());
}

Hive_Accessor::~Hive_Accessor()
{
	reg_close();
}

int
Hive_Accessor::fill_linked_relation_array(const Windows_Information * win_info)
{
	IF_NULL_RETURN_VALUE(win_info, -1);

	if (true || win_info->get_windows_version() > WINDOWS_ME &&
	win_info->get_windows_version() < WINDOWS_VISTA)	// NT Framework
	{
		// 填充HKEY_LOCAL_MACHINE根键信息
		// todo: hardware shadow which one?
		Link_Relation tmp(std::string("HARDWARE"), std::string("HKEY_LOCAL_MACHINE\\SYSTEM\\???"));
		tmp.shadow(true);	// 映射键
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(tmp);
		tmp.key_name(std::string("SYSTEM\\CurrentControlSet"));
		tmp.target(std::string("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001"));
		tmp.shadow(true);	// 映射键
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(tmp);
		// 主键
		reg_roots_[HKEY_LOCAL_MACHINE].root_key(HKEY_ROOTS[HKEY_LOCAL_MACHINE]);
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(Link_Relation(std::string("SAM"),
		win_info->get_directorie(SYSTEM_DIR) + std::string("/config/SAM1"))); //TODO:暂且改着
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(Link_Relation(std::string("SECURITY"),
		win_info->get_directorie(SYSTEM_DIR) + std::string("/config/SECURITY1")));
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(Link_Relation(std::string("SOFTWARE"),
		win_info->get_directorie(SYSTEM_DIR) + std::string("/config/software1")));
		reg_roots_[HKEY_LOCAL_MACHINE].add_relation(Link_Relation(std::string("SYSTEM"),
		win_info->get_directorie(SYSTEM_DIR) + std::string("/config/system1")));

		// 填充HKEY_USERS根键信息
		reg_roots_[HKEY_USERS].root_key(HKEY_ROOTS[HKEY_USERS]);
		reg_roots_[HKEY_USERS].add_relation(Link_Relation(std::string(".DEFAULT"),
		win_info->get_directorie(SYSTEM_DIR) + std::string("/config/default1")));

		// 填充HKEY_CLASS_ROOT根键信息
		reg_roots_[HKEY_CLASS_ROOT].root_key(HKEY_ROOTS[HKEY_CLASS_ROOT]);
		tmp.key_name(std::string(""));	// 无别名，根键直接映射
		tmp.target(std::string("HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes"));
		tmp.shadow(true);	// 映射键
		reg_roots_[HKEY_CLASS_ROOT].add_relation(tmp);


		// 填充HKEY_CURRENT_USER根键信息
		reg_roots_[HKEY_CURRENT_USER].root_key(HKEY_ROOTS[HKEY_CURRENT_USER]);
		tmp.key_name(std::string(""));	// 无别名，根键直接映射
		tmp.target(std::string("HKEY_USERS\\.DEFAULT"));
		tmp.shadow(true);	// 映射键
		reg_roots_[HKEY_CURRENT_USER].add_relation(tmp);

		// 填充HKEY_CURRENT_CONFIG根键信息
		reg_roots_[HKEY_CURRENT_CONFIG].root_key(HKEY_ROOTS[HKEY_CURRENT_CONFIG]);
		tmp.key_name(std::string(""));
		tmp.target(std::string("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet"));
		tmp.shadow(true);	// 映射键
		reg_roots_[HKEY_CURRENT_CONFIG].add_relation(tmp);

	}
	return 0;
}

int
Hive_Accessor::reg_open(HKEY root, const char * path, int mode)
{
	IF_NULL_RETURN_VALUE(path, -1);
	if (root < 0 || root >= HKEY_INVALID_ROOT) return -1;
	std::string	goal(path);
	std::string	prefix;
	reg_close(); // 关闭之前可能已经打开的注册表文件
	// 打开的是SYSTEM\CurrentControlSet键，先取得其真正的映射目标
	if (0 == goal.find("SYSTEM") &&
	!s_is_current_controlset_maped) {
		s_is_current_controlset_maped = true;	// 保证只映射一次
		if (0 == reg_open(HKEY_LOCAL_MACHINE, "SYSTEM\\Select")) {
			unsigned int map = 0;
			if (get_value("Current", map)) {
				char map_target[64] = {0};
				sprintf(map_target, "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet00%d", map);
				reg_roots_[HKEY_LOCAL_MACHINE].link_relation(std::string("SYSTEM\\CurrentControlSet")) = 
				std::string(map_target);
			}
			reg_close();
		}
	}
	// 只有一个根键，且为匿名映射键
	if (1 == reg_roots_[root].link_relations().size() &&
		reg_roots_[root].link_relations()[0].key_name().empty() &&
		reg_roots_[root].link_relations()[0].shadow()) {		
		prefix = reg_roots_[root].link_relations()[0].target();
		size_t dpos = prefix.find_first_of("\\");
		return reg_open(prefix.substr(0, dpos).c_str(), (prefix.substr(dpos + 1) + "\\" + path).c_str());
	}
	Hive_Root::Link_Relations::const_iterator end = (reg_roots_[root].link_relations()).end();
	Hive_Root::Link_Relations::const_iterator index = (reg_roots_[root].link_relations()).begin();
	printf("Wanna open %s with path: %s.\n", reg_roots_[root].root_key().c_str(), path);
	for (; index != end; ++index) {
		prefix = index->key_name();
		printf("try match %s to %s\n", goal.c_str(), prefix.c_str());
		if (0 == goal.find(prefix) && 
		(goal.length() == prefix.length() || goal.at(prefix.length()) == '\\')) {
			printf("find %s in %s at pos %u\n", prefix.c_str(), goal.c_str(), goal.find(prefix));
			break;
		}
	}
	if (index != end) {
		if (index->shadow()) { // 处理映射键
			printf("Produce shadow key...\n");
			size_t subkey_pos = goal.find(prefix) + prefix.length();
			size_t pos = index->target().find_first_of('\\');
			if (std::string::npos != pos) {
				int i = HKEY_LOCAL_MACHINE;				
				prefix.assign(index->target(), 0, pos);
				for (; i < HKEY_INVALID_ROOT; ++i) {
					if (reg_roots_[i].root_key() == prefix) break;					
				}
				printf("head: %s\n", reg_roots_[i].root_key().c_str());
				prefix = index->target().substr(pos + 1);
				printf("prefix: %s\n", prefix.c_str());
				if (i < HKEY_INVALID_ROOT)
					return reg_open(reg_roots_[i].root_type(), (prefix + goal.substr(subkey_pos)).c_str());				
			}
		} else if (utility::is_file_exist(index->target())) {
			printf("Produce origin key...\n");
			hive_ = openHive(index->target().c_str(), mode);
			if (NULL != hive_) {
				prefix_.assign(goal, prefix.length(), goal.length() - prefix.length()); 
				//printf("::%s\n", prefix_.c_str());				
				int newofs = ::trav_path(hive_, root_node_offset() + 4, prefix_.c_str(), 
				TPF_NK | TPF_EXACT);
				if (newofs) {
					cdofs_ = origin_offset_ = newofs;
					printf("open hive success offset %d.\n", newofs);
					return 0;
				} else { // 无法打开路径，失败
					reg_close();
					printf("open hive failed.\n");
				}
			}
		}		
	}
	
	return -1;
}

int
Hive_Accessor::reg_open(const char * root_name, const char *path, int mode)
{
	for (int i = 0; i < HKEY_INVALID_ROOT; ++i) {
		if (0 == strcmp(HKEY_ROOTS[i], root_name)) {
			return reg_open((HKEY)i, path, mode);
		}
	}
	return -1;
}

void
Hive_Accessor::reg_close()
{
	if (NULL != hive_) {
		if (hive_->state & HMODE_DIRTY) {
			if (0 == ::writeHive(hive_))	printf("Hive write back\n");
		}
		::closeHive(hive_);
		cdofs_ = 0;
		hive_ = NULL;
	}
}

bool	
Hive_Accessor::is_available() const
{
	return (NULL != hive_);
}

int
Hive_Accessor::root_node_offset() const
{
	return NULL != hive_ ? hive_->rootofs : 0;
}

bool	
Hive_Accessor::enter_key(const char *path)
{
	IF_NULL_RETURN_VALUE(path, false);
	IF_NULL_RETURN_VALUE(hive_, false);
	printf("into %s start...\n", path);
	// 去除键路径开始的'\'，该符号代表根路径
	int newofs = ::trav_path(hive_, origin_offset_ + 4, '\\' == *path ? path + 1 : path, 
	TPF_NK | TPF_EXACT);
	if (newofs) {
		cdofs_ = newofs;
		printf("Into %s success\n", path);	
		return true;	
	}
	printf("Into %s failed\n", path);
	return false;
}

int
Hive_Accessor::add_key(const char *key_name)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	if (hive_) {		
		if (NULL != ::add_key(hive_, origin_offset_ + 4, key_name)) {
			printf("Add key %s success.\n", key_name);
			return 0;
		}
		return -1;
	} else {
		puts("Hive_Accessor is not available now.\n");
	}
	return -2;
}

// return 0 - success -1/1 - failed
int
Hive_Accessor::remove_key(const char * key_name)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	return ::del_key(hive_, origin_offset_ + 4, key_name);
}

int
Hive_Accessor::remove_allkeys(const char * key_name)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	/*if (enter_key(key_name))*/ {
		// todo: 对子路径支持不够，同系列函数可能都存在这个问题，待测
		return ::rdel_keys(hive_, key_name, origin_offset_ + 4);
	}
	return -1;
}

int
Hive_Accessor::delete_value(const char * val_name)
{
	IF_NULL_RETURN_VALUE(val_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	// 处理键路径
	std::string path('\\' == *val_name ? val_name + 1 : val_name); 
	size_t pos = 0;
	bool	path_contain = split_for_val_name_and_enter_key(path, pos);
	return ::del_value(hive_, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : path.c_str(),
	TPF_EXACT);
}

bool
Hive_Accessor::split_for_val_name_and_enter_key(const std::string & path, size_t & pos)
{
	size_t pos_delimiter = path.find_last_of('\\');
	if (pos_delimiter > 0 && pos_delimiter != std::string::npos) {
		if (enter_key(path.substr(0, pos_delimiter).c_str())) {
			pos = pos_delimiter;
			return true;
		}		
	}
	cdofs_ = origin_offset_; // 复位到相对基路径下，以确保每次操作的键及值均是相对于基路径的
	return false;
}

int
Hive_Accessor::add_value(const char * name, int type)
{
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	// 处理键路径
	std::string path('\\' == *name ? name + 1 : name); 
	size_t pos = 0;
	bool	path_contain = split_for_val_name_and_enter_key(path, pos);

	if (type >= REG_NONE && type <= REG_QWORD) {
		if (NULL != ::add_value(hive_, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : 
			path.c_str(), type)) {
			return 0;/*::put_dword(hive_, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : 
			path.c_str(), TPF_EXACT, value);*/
		}
	}
	return -1;
}

int
Hive_Accessor::value_modify(const char * name, int value)
{
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	std::string path('\\' == *name ? name + 1 : name); // 去除键路径开始的'\'，该符号代表根路径
	size_t pos = 0;
	bool	path_contain = split_for_val_name_and_enter_key(path, pos);
	return ::put_dword(hive_, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : path.c_str(),
		TPF_EXACT, value);
}

bool
Hive_Accessor::get_value(const char * name, unsigned int &value)
{
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	std::string path('\\' == *name ? name + 1 : name); // 去除键路径开始的'\'，该符号代表根路径
	size_t pos = 0;
	bool	path_contain = split_for_val_name_and_enter_key(path, pos);	
	return (::get_dword(hive_, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : 
	path.c_str(), &value, TPF_EXACT) == 0 ? true : false);
}

size_t
Hive_Accessor::get_value(const char * name, wchar_t *& value)
{
	IF_NULL_RETURN_VALUE(name, 0);
	//IF_NOT_EQUAL_RETURN_VALUE(NULL, value, -2);
	IF_NULL_RETURN_VALUE(hive_, 0);
	std::string path('\\' == *name ? name + 1 : name); // 去除键路径开始的'\'，该符号代表根路径
	size_t pos = 0;
	bool	path_contain = split_for_val_name_and_enter_key(path, pos);
	current_key_path();
	struct keyval * val = 
	get_val2buf(hive_, NULL, cdofs_ + 4, path_contain ? path.substr(pos + 1).c_str() : path.c_str(), 
	REG_SZ, TPF_VK_EXACT);
	if (NULL != val) {
		value = new wchar_t [val->len / 2]; // val->len 已经包含结束符了
		memset(value, 0, (val->len / 2) * sizeof(wchar_t));
		utility::TCHAR *ptr = reinterpret_cast<utility::TCHAR *>(&(val->data));
		std::copy(ptr, ptr + val->len / 2, value);
		//printf("string len(data len div 2): %d\n", val->len / 2);
		//if (NULL != value) {						
			//for (int i = 0; i < val->len / 2; ++i) {
				//printf("%x\t", value[i]);
			//}
		//}

		printf("printf: %S\n", value);
		return val->len;
	}else printf("get REG_SZ failed\n");
	return 0;
}

int
Hive_Accessor::remove_allvalues(const char * key_name)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	if (enter_key(key_name)) {
		return ::del_allvalues(hive_, origin_offset_ + 4);
	}
	return -1;
}

char *
Hive_Accessor::current_key_path()
{
	static char path[1024] = {0};
	memset(path, 0, sizeof(path));
	IF_NULL_RETURN_VALUE(hive_, path);
	get_abs_path(hive_, cdofs_ + 4, path, 1023);
	printf("current path: %s\n", path);
	return path;
}

bool
Hive_Accessor::have_any_subkey(const char * path)
{
	IF_NULL_RETURN_VALUE(path, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	struct nk_key *key = NULL;
	if (enter_key(path)) {
		key = (struct nk_key *)(hive_->buffer + cdofs_ + 4);
		return key->no_subkeys > 0 ? true : false;
	}
	return false;
}

int
Hive_Accessor::subkey_foreach(const char * key_name, key_callback kcb, void * user_data)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(kcb, -1);
	return ::subkey_handle(hive_, key_name, origin_offset_ + 4, kcb, NULL, user_data);
}

int
Hive_Accessor::value_foreach(const char * key_name, val_callback vcb, void * user_data)
{
	IF_NULL_RETURN_VALUE(key_name, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(vcb, -1);
	return ::subkey_handle(hive_, key_name, origin_offset_ + 4, NULL, vcb, user_data);
}

const Hive_Root	&
Hive_Accessor::take_root(HKEY hkey) const
{
	return (hkey < 0 || hkey >= HKEY_INVALID_ROOT) ? reg_roots_[HKEY_INVALID_ROOT] :
	reg_roots_[hkey];
}

const Hive_Root	&
Hive_Accessor::take_root(const char * name) const
{
	IF_NULL_RETURN_VALUE(name, reg_roots_[HKEY_INVALID_ROOT]);
	int k = HKEY_LOCAL_MACHINE;
	for (; k < HKEY_INVALID_ROOT; ++k) {
		if (reg_roots_[k].root_key() == name) break; 
	}
	return reg_roots_[k];
}

int 
Hive_Accessor::get_value_length(const char * val_name) const
{
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(val_name, -1);
	return ::get_val_len(hive_, origin_offset_ + 4, val_name, TPF_VK);
}

int
Hive_Accessor::get_value_type(const char * val_name) const
{
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(val_name, -1);
	return ::get_val_type(hive_, origin_offset_ + 4, val_name, TPF_VK);
}

int
Hive_Accessor::get_value(const char * name, void * buffer, size_t len, int & type) const
{
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(buffer, -1);
	int length = get_value_length(name);
	int reg_type = get_value_type(name);
	if (0 != length && -1 != reg_type) { // valid value name
	// valid buffer and suitable size
		type = reg_type;
		if (NULL != buffer && len >= static_cast<size_t>(length)) { 
			void *data = 
			::get_val_data(hive_, origin_offset_ + 4, name, reg_type, TPF_VK);
			if (NULL != data) {
				memcpy(buffer, data, length);
				return 0;
			}
		}
		return -2; // not suitable supplied buffer length
	}
	return -3; // can't take value length or type of supplied name
}

int
Hive_Accessor::set_value(const char * name, void * buffer, size_t len, int type)
{
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(buffer, -1);
	struct keyval * kval = NULL;
	int reg_type = get_value_type(name);
	int length = get_value_length(name);
	if (length >= 0 && -1 != reg_type) {	// exist value
		if (-1 == type || type == reg_type) {		// verify type
			kval = (struct keyval *)malloc(sizeof(struct keyval) + len);
			if (NULL != kval) {
				kval->len = len;
				memcpy(&kval->data, buffer, len);
				int ret = 
				put_buf2val(hive_, kval, origin_offset_ + 4, name, reg_type, TPF_VK);
				FREE(kval);
				return ret; // TODO: should return result of invork put_buf2val()
			}
		}
	}
	return -1;
}

const char * 
Hive_Accessor::get_type_string(unsigned type)
{
	static const char * type_str[REG_MAX] = {"REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY", "REG_DWORD", 
	"REG_DWORD_BIG_ENDIAN", "REG_LINK", "REG_MULTI_SZ", "REG_RESOURCE_LIST", 
	"REG_FULL_RESOURCE_DESCRIPTOR", "REG_RESOURCE_REQUIREMENTS_LIST", "REG_QWORD"};
	return (type > REG_NONE && type < REG_MAX) ? type_str[type] : type_str[REG_NONE];
}

int
Hive_Accessor::value_rename(const char * srcname, const char * dstname)
{
	IF_NULL_RETURN_VALUE(srcname, -1);
	IF_NULL_RETURN_VALUE(dstname, -1);
	IF_NULL_RETURN_VALUE(hive_, -1);
	int ret = 0;
	if (0 != strcmp(srcname, dstname)) {
		int type = get_value_type(srcname);
		if (-1 != type) {
			int len = get_value_length(srcname);
			if (len > 0) {
				char * buf = new char [len];
				if (NULL != buf) {
					get_value(srcname, buf, len, type);
					if (0 == ::del_value(hive_, cdofs_ + 4, srcname, TPF_EXACT)) {
						if (::add_value(hive_, cdofs_ + 4, dstname, type) > 0) {
							ret = set_value(dstname, buf, len, type);
						}
					}
					delete buf;
					return ret;
				}
			}
		}
	}
	return -1;
}

int
Hive_Accessor::key_export(const char *name, const char *filename, const char *prefix) const
{
	IF_NULL_RETURN_VALUE(hive_, -1);
	IF_NULL_RETURN_VALUE(name, -1);
	IF_NULL_RETURN_VALUE(filename, -1);
	IF_NULL_RETURN_VALUE(prefix, -1);
	::export_key(hive_, cdofs_ + 4, name, filename, prefix);
	return 0;
}

bool
Hive_Accessor::trace_to_parent_key()
{
	return enter_key("../");
}
